int	utf8_decode(char *B, unsigned int &len, unsigned int despl);
void fgets_toWhite(char *cadena, int n, FILE *fichero);
#include <iostream>
#include <fstream>
#include <cctype>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
using namespace std;
#define LENMAX 100


#ifndef _SOPA_DE_LETRAS_
#define _SOPA_DE_LETAS_

class sopaDeLetras{
	private:
		wchar_t **sopa;
		int W,H;
	public:
		sopaDeLetras(FILE *f);
		wchar_t buscarRelativo(int origenx,int origeny,int radio,int direccion);
		void imprime(void);
		int getW(void){return W;};
		int getH(void){return H;};
		void toUpper(void);


};



sopaDeLetras::sopaDeLetras(FILE *f){
	char wi[10],he[10];
	char B[LENMAX], byte[1];
	unsigned int despl = 0, len = 0;
	wchar_t caracter;
	//Lee tamaño de la matriz
	fgets_toWhite(wi,10,f);
	fgets_toWhite(he,10,f);
	W = atoi(wi);
	H = atoi(he);
	//Creacion de la matriz
	sopa = new wchar_t*[W];
	for (int i = 0; i < W; ++i)sopa[i] = new wchar_t[H];



	for(int i=0;i<H;i++){
		for(int j=0;j<W;j++){
		despl=0;
		len=0;
		byte[0]=0;
		//Inicializa B y p
		for(int k=0;k<LENMAX;k++)B[k]=0;

		/*Lee desde el archivo hasta un blanco o salto de linea*/
		/*Asume que la linea es no vacia*/
		for(int k=0;k<5;k++){
			fread(byte,1,1,f);
			if((byte[0] != 10) && (byte[0] != 32) && (byte[0] != 9)){
				B[k] = byte[0];
			}
			else break;
		}

		/*Pasa de B, que contiene bytes a caracter que es un caracter utf32*/
		caracter = utf8_decode(B, len, despl);
		//Agrega el caracter (en UTF32) a la matriz
		sopa[j][i] = caracter;
		}
	}
	

}


/*********************************************************************************
Busca una posicion dentro de la sopa relativa al origen a una distancia de 'radio'
en la direccion especificada por 'direccion'.
'direccion' puede tener valores del 1 al 8 y se corresponden con cada una de las
posiciones que rodean a un casillero. Se consideran en sentido horario como sigue:
1: arriba - 2: arriba derecha - 3: izquierda .. etc
Si no existe tal posicion retorna -1
*********************************************************************************/
wchar_t sopaDeLetras::buscarRelativo(int origenx,int origeny,int radio,int direccion){
	if((origenx>W-1) || (origenx<0) || (origeny>H-1) || (origeny<0)) return -1;
	switch(direccion){
	case 1:
		if(origeny-radio<0)return -1;
		else return sopa[origenx][origeny-radio];
		break;
	case 2:
		if((origenx+radio>W-1) || (origeny-radio<0))return -1;
		else return sopa[origenx+radio][origeny-radio];
		break;
	case 3:
		if(origenx+radio>W-1)return -1;
		else return sopa[origenx+radio][origeny];
		break;
	case 4:
		if((origenx+radio>W-1) || (origeny+radio>H-1))return -1;
		else return sopa[origenx+radio][origeny+radio];
		break;
	case 5:
		if(origeny+radio>H-1)return -1;
		else return sopa[origenx][origeny+radio];
		break;
	case 6:
		if((origenx-radio<0) || (origeny+radio>H-1))return -1;
		else return sopa[origenx-radio][origeny+radio];
		break;
	case 7:
		if(origenx-radio<0)return -1;
		else return sopa[origenx-radio][origeny];
		break;
	case 8:
		if((origenx-radio<0) || (origeny-radio<0 ))return -1;
		else return sopa[origenx-radio][origeny-radio];
		break;

	}

}

void sopaDeLetras::imprime(void){
	for(int i=0;i<H;i++){
		for(int j=0;j<W;j++)cout<<sopa[j][i]<<" ";
		cout<<endl;
	}

}

void sopaDeLetras::toUpper(void){
	for(int i=0;i<W;i++){
		for(int j=0;j<H;j++){
			sopa[i][j] = toupper(sopa[i][j]);
		}
	}


}

#endif



int	utf8_decode(char *B, unsigned int &len, unsigned int despl){
	int c = 0, k;
	unsigned char b;
	b = B[despl]; /*first byte of a B*/
	if ((b & 0x80) == 0x00)
		c = b, len = 0;
	else if ((b & 0xe0) == 0xc0)
		c = b & 0x1f, len = 1;
	else if ((b & 0xf0) == 0xe0)
		c = b & 0x0f, len = 2;
	else if ((b & 0xf8) == 0xf0)
		c = b & 0x07, len = 3;
	for (k = 0; k < len; ++k) {
		c <<= 6;
		b = B[despl+k+1];
		c |= (b & 0x3f);
	}
	//Para que len contenga el largo en bytes
	len+=1;
	return c;

}


void fgets_toWhite(char *cadena, int n, FILE *fichero){
	char aux;
	for(int i=0;i<n;i++){
		aux = fgetc(fichero);
		if((aux == 10) || (aux == 32))break;
		else cadena[i] = aux;
	}

}
